package com.allwees.bs.module.scm.service.impl;

import com.allwees.bs.core.modelbase.transform.ObjectTransformFactory;
import com.allwees.bs.module.base.service.impl.BoServiceImpl;
import com.allwees.bs.module.scm.bo.EnteredWarehouseBo;
import com.allwees.bs.module.scm.bo.ScmOrderShippingBo;
import com.allwees.bs.module.scm.dao.ScmShippingOrderDao;
import com.allwees.bs.module.scm.entity.ScmPickOrderSku;
import com.allwees.bs.module.scm.entity.ScmShippingOrder;
import com.allwees.bs.module.scm.entity.ScmShippingOrderSku;
import com.allwees.bs.module.scm.mq.event.EnteredWarehouseMqEvent;
import com.allwees.bs.module.scm.req.EnteredWarehouseReq;
import com.allwees.bs.module.scm.req.RefundShippingOrderSkuReq;
import com.allwees.bs.module.scm.req.ShippingOrderEnteredReq;
import com.allwees.bs.module.scm.req.internal.EnteredWarehouseSkuReq;
import com.allwees.bs.module.scm.service.ScmShippingOrderService;
import com.allwees.bs.module.scm.service.ScmShippingOrderSkuService;
import com.allwees.bs.module.scm.transform.ScmTransformFactoryStrategy;
import com.allwees.bs.module.scm.util.ScmNoUtil;
import com.allwees.bs.module.scm.wf.EScmShippingOrderAction;
import com.allwees.bs.module.scm.wf.EScmShippingOrderState;
import com.allwees.core.common.constant.EStatus;
import com.allwees.core.common.util.UuidUtil;
import com.allwees.core.mq.rabbitmq.MqUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.Set;

/**
 * scm 物流发货单
 *
 * @author mouhn
 * @since 2020-1-3 17:39
 */
@Service
public class ScmShippingOrderServiceImpl extends BoServiceImpl<ScmShippingOrderDao, ScmShippingOrder> implements ScmShippingOrderService {

    @Autowired
    private ScmShippingOrderSkuService shippingOrderSkuService;

    @Override
    @Transactional
    public boolean create(ScmOrderShippingBo shippingBo) {
        ObjectTransformFactory<ScmPickOrderSku, ScmShippingOrderSku> factory = ScmTransformFactoryStrategy.strategy(ScmPickOrderSku.class, ScmShippingOrderSku.class);

        String uuid = UuidUtil.generate();

        ScmShippingOrder shippingOrder = shippingBo.shippingOrder();
        shippingOrder.setNo(ScmNoUtil.genShippingOrderNo(uuid))
                .setUuid(uuid);

        shippingOrder.start(EScmShippingOrderState.START, EScmShippingOrderAction.SUPPLIER_WAIT_ENTER_WAREHOUSE);
        create(shippingOrder);

        for (ScmPickOrderSku pickOrderSku : shippingBo.getPickOrderSkus()) {
            shippingOrderSkuService.create(factory.transform(pickOrderSku).setShippingOrderUuid(shippingOrder.getUuid()));
        }
        return true;
    }

    @Override
    public void logisticsPackEnteredWarehouse(ShippingOrderEnteredReq req) {

        for (String uuid : req.getShippingOrderUuids()) {
            ScmShippingOrder shippingOrder = checkByUuid(uuid);
            shippingOrder.assertStatus(EStatus.SCM_WAIT_ENTER);

            ScmShippingOrder update = new ScmShippingOrder(uuid);
            update.setLogisticsPackStatus(EStatus.SCM_ENTERED);
            updateByUuid(update);
        }
    }

    @Override
    public void enteredWarehouse(EnteredWarehouseReq req) {

        HashSet<String> shippingOrderUuids = new HashSet<>();

        for (EnteredWarehouseSkuReq enteredWarehouse : req.getEnteredWarehouseSkus()) {
            ScmShippingOrderSku shippingOrderSku = shippingOrderSkuService.enteredWarehouse(enteredWarehouse, req.getBranchUserUuid());

            shippingOrderUuids.add(shippingOrderSku.getShippingOrderUuid());
        }

        if (CollectionUtils.isEmpty(shippingOrderUuids)) {
            return;
        }

        shippingOrderUuids.forEach(shippingOrderUuid -> {
            if (shippingOrderSkuService.allEnterWarehouse(shippingOrderUuid)) {
                _signal(shippingOrderUuid, EScmShippingOrderAction.PLATFORM_ENTERED_WAREHOUSE);
            }
        });

        ScmShippingOrder shippingOrder = findByUuid(CollectionUtils.get(shippingOrderUuids, 0));
        _mqEvent(shippingOrder.getWarehouseUuid(), req.getBranchUserUuid(), req.getShippingOrderSkuUuids());
    }

    @Override
    public void refund(RefundShippingOrderSkuReq req) {
        Set<String> shippingOrderUuids = new HashSet<>();
        for (String orderSkuUuid : req.getShippingOrderSkuUuids()) {
            ScmShippingOrderSku shippingOrderSku = shippingOrderSkuService.refund(orderSkuUuid, req.getReason(), req.getBranchUserUuid());
            shippingOrderUuids.add(shippingOrderSku.getShippingOrderUuid());
        }

        shippingOrderUuids.forEach(shippingOrderUuid -> {
            if (shippingOrderSkuService.allRefund(shippingOrderUuid)) {
                _signal(shippingOrderUuid, EScmShippingOrderAction.PLATFORM_ALL_REFUND);
            }
        });
    }

    private boolean _signal(String uuid, EScmShippingOrderAction action) {

        ScmShippingOrder shippingOrder = checkByUuid(uuid);
        shippingOrder.signal(action);
        return updateByUuid(shippingOrder);
    }

    private void _mqEvent(String warehouseUuid, String operatorUuid, Set<String> shippingOrderSkuUuids) {

        EnteredWarehouseBo enteredWarehouseBo = new EnteredWarehouseBo()
                .setOperatorUuid(operatorUuid)
                .setWarehouseUuid(warehouseUuid)
                .setEnteredWarehouseSkus(shippingOrderSkuService.findByUuids(shippingOrderSkuUuids));

        MqUtil.send(new EnteredWarehouseMqEvent(UuidUtil.generate(), enteredWarehouseBo));
    }
}
